#include "mylog.hpp"
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <chrono>

void bench(const std::string &logger_name, size_t thread_num,
        size_t msg_len, size_t msg_count){
    mylog::Logger::ptr logger = mylog::getlogger(logger_name);
    if (logger.get() == nullptr){ 
        return;
    }
    std::string msg(msg_len, '1');
    size_t msg_pre_thread = msg_count / thread_num;
    std::cout << "线程数量: " << thread_num << std::endl;
    std::cout << "日志数量: " << msg_count << std::endl;
    std::cout << "日志大小: " << msg_len * msg_count / 1024 / 1024 << "MB" << std::endl;
    std::vector<std::thread> threads;
    std::vector<double> cost_time(thread_num);

    for (int i = 0; i < thread_num; i++){
        threads.emplace_back([&, i]()
                             {
            // 开始计时
            auto start=std::chrono::high_resolution_clock::now();
            for (size_t j = 0; j < msg_pre_thread; j++){
                logger->INFO("%s", msg.c_str());
            }
            auto end=std::chrono::high_resolution_clock::now();
            std::chrono::duration<double> cost=end-start;
            cost_time[i]=cost.count();
            auto avg=msg_pre_thread/cost_time[i];
            std::cout << "线程" << i << " 耗时: " << cost_time[i] << "s  ";
            std::cout << "平均每秒输出: " << avg << std::endl;
        });
    }

    for(auto &thread : threads){ 
        thread.join();
    }
    double max_cost = 0;
    for(auto cost : cost_time){
        max_cost = max_cost > cost ? max_cost : cost;
    }
    std::cout << "总消耗时间: " << max_cost << "s" << std::endl;
    std::cout << "平均每秒输出: " << (size_t)(msg_count / max_cost) << std::endl;
    std::cout << "平均每秒输出: " << msg_count * msg_len / max_cost / 1024 / 1024 << "MB" << std::endl;
}

void sync_bench_thread_log(size_t thread_num, size_t msg_len, size_t msg_count){
    std::string logger_name = "sync_bench_logger";
    std::cout << "===================================================" << std::endl;
    std::cout << "同步日志测试: " << thread_num << " thread_num, " << msg_count << " msg_count" << std::endl;
    std::unique_ptr<mylog::LoggerBuilder> builder(new mylog::GlobalLoggerBuilder());
    builder->BuildLoggerName(logger_name);
    builder->BuildLoggerType(mylog::LoggerType::SYNC_LOGGER);
    builder->BuildFormatter("%m%n");
    builder->BuildSink<mylog::FileSink>("FileLog/bench.log");
    builder->Build();
    bench(logger_name, thread_num, msg_len, msg_count);
    std::cout << "===================================================" << std::endl;
}

void async_bench_thread_log(size_t thread_num, size_t msg_len, size_t msg_count){
    std::string logger_name = "async_bench_logger";
    std::cout << "===================================================" << std::endl;
    std::cout << "异步日志测试: " << thread_num << " thread_num, " << msg_count << " msg_count" << std::endl;
    std::unique_ptr<mylog::LoggerBuilder> builder(new mylog::GlobalLoggerBuilder());
    builder->BuildLoggerName(logger_name);
    builder->BuildLoggerType(mylog::LoggerType::ASYNC_LOGGER);
    builder->BuildFormatter("%m%n");
    builder->BuildSink<mylog::FileSink>("FileLog/bench.log");
    builder->SetUnsafeType();
    builder->Build();
    bench(logger_name, thread_num, msg_len, msg_count);
    std::cout << "===================================================" << std::endl;
}

int main(){
    remove("FileLog/bench.log");
    sync_bench_thread_log(1, 100, 1000000);
    remove("FileLog/bench.log");
    sync_bench_thread_log(5, 100, 1000000);
    remove("FileLog/bench.log");
    async_bench_thread_log(1, 100, 1000000);
    remove("FileLog/bench.log");
    async_bench_thread_log(5, 100, 1000000);
    mylog::shutdown();
    return 0;
}